package com.d3works.apps.sale.service.configurator;

import com.d3works.apps.sale.db.ConfiguratorCreator;
import com.d3works.apps.sale.db.ConfiguratorFormula;
import com.d3works.apps.sale.exception.SaleExceptionMessage;
import com.d3works.apps.tool.MetaTool;
import com.d3works.db.EntityHelper;
import com.d3works.db.Model;
import com.d3works.exception.D3worksException;
import com.d3works.exception.db.repo.TraceBackRepository;
import com.d3works.i18n.I18n;
import com.d3works.inject.Beans;
import com.d3works.meta.db.MetaJsonField;
import com.d3works.script.GroovyScriptHelper;
import com.d3works.script.ScriptBindings;

public class ConfiguratorFormulaServiceImpl implements ConfiguratorFormulaService {

  @Override
  public void checkFormula(ConfiguratorFormula formula, ConfiguratorCreator creator)
      throws D3worksException {
    ScriptBindings defaultValueBindings =
        Beans.get(ConfiguratorCreatorService.class).getTestingValues(creator);
    Object result = new GroovyScriptHelper(defaultValueBindings).eval(formula.getFormula());
    String wantedTypeName;
    MetaJsonField metaJsonField = formula.getMetaJsonField();
    if (metaJsonField != null) {
      wantedTypeName =
          MetaTool.getWantedClassName(
              metaJsonField, MetaTool.jsonTypeToType(metaJsonField.getType()));
    } else {
      wantedTypeName = formula.getMetaField().getTypeName();
    }

    if (result == null) {
      throw new D3worksException(
          formula,
          TraceBackRepository.CATEGORY_CONFIGURATION_ERROR,
          I18n.get(SaleExceptionMessage.CONFIGURATOR_CREATOR_SCRIPT_ERROR));
    } else if (!Beans.get(ConfiguratorService.class)
            .areCompatible(wantedTypeName, getCalculatedClassName(result))
        && !wantedTypeName.equals("one-to-many")
        && !wantedTypeName.equals("many-to-many")) {
      throw new D3worksException(
          formula,
          TraceBackRepository.CATEGORY_CONFIGURATION_ERROR,
          I18n.get(SaleExceptionMessage.CONFIGURATOR_CREATOR_FORMULA_TYPE_ERROR),
          result.getClass().getSimpleName(),
          wantedTypeName);
    }
  }

  @Override
  public String getCalculatedClassName(Object calculatedValue) {
    if (calculatedValue instanceof Model) {
      return EntityHelper.getEntityClass(calculatedValue).getSimpleName();
    } else {
      return calculatedValue.getClass().getSimpleName();
    }
  }
}
